package top.italks.demo.pay.product.controller;

import com.alibaba.fastjson.JSON;
import top.italks.demo.entity.AliOrderEntity;
import top.italks.demo.pay.common.api.PayService;
import top.italks.demo.pay.common.bean.*;
import top.italks.demo.pay.common.http.UriVariables;
import top.italks.demo.pay.platform.ali.AliPayConfig;
import top.italks.demo.pay.platform.ali.api.AliPayConfigStorage;
import top.italks.demo.pay.platform.ali.api.AliPayService;
import top.italks.demo.pay.platform.ali.bean.AliTransactionType;
import top.italks.demo.pay.platform.ali.bean.AliTransferType;
import top.italks.demo.pay.request.QueryOrder;
import top.italks.demo.service.AliOrderService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.UUID;

/**
 * 发起支付入口
 *
 * @author: egan
 * @email test@gmail.com
 * @date 2016/11/18 0:25
 */
@RestController
@RequestMapping("ali")
public class AliPayController {

    private PayService service = null;

    private static Random random = new Random();

    @Resource
    AliPayConfig aliPayConfig;

    @Resource
    AliOrderService aliOrderService;

    @PostConstruct
    public void init() {
        service = new AliPayService(new AliPayConfigStorage(aliPayConfig));
    }

    /**
     * 跳到支付页面
     * 针对实时支付,即时付款
     *
     * @param price 金额
     * @return 跳到支付页面
     */
    @RequestMapping(value = "toPay.html", produces = "text/html;charset=UTF-8")
    public String toPay(BigDecimal price) {
        //及时收款 DIRECT
        PayOrder order = new PayOrder("订单title", "摘要",
                new BigDecimal(random.nextInt(10))
                , UUID.randomUUID().toString().replace("-", ""), AliTransactionType.DIRECT);
        Map orderInfo = service.orderInfo(order);
        return service.buildRequest(orderInfo, MethodType.POST);
    }

    /**
     * 跳到支付页面
     * 针对实时支付,即时付款
     *
     * @param price 金额
     * @return 跳到支付页面
     */
    @RequestMapping(value = "toPayWap.html", produces = "text/html;charset=UTF-8")
    public String toPayWap(BigDecimal price) {
        //WAP
        PayOrder order = new PayOrder("订单title", "摘要",
                new BigDecimal(random.nextInt(10)),
                UUID.randomUUID().toString().replace("-", ""), AliTransactionType.WAP);

        Map orderInfo = service.orderInfo(order);
        return service.buildRequest(orderInfo, MethodType.POST);
    }

    /**
     * 获取支付预订单信息
     *
     * @return 支付预订单信息
     */
    @RequestMapping("app")
    public Map<String, Object> app() {
        Map<String, Object> data = new HashMap<>();
        data.put("code", 0);
        PayOrder order = new PayOrder("订单title", "摘要",
                new BigDecimal(random.nextInt(10)),
                UUID.randomUUID().toString().replace("-", ""));
        //App支付
        order.setTransactionType(AliTransactionType.APP);
        data.put("orderInfo", UriVariables.getMapToParameters(service.orderInfo(order)));
        return data;
    }

    /**
     * 获取二维码图像
     * 二维码支付
     *
     * @param price 金额
     * @return 二维码图像
     */
    @RequestMapping(value = "toQrPay.jpg", produces = "image/jpeg;charset=UTF-8")
    public byte[] toWxQrPay(BigDecimal price) throws IOException {
        //获取对应的支付账户操作工具（可根据账户id）
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        price = new BigDecimal(random.nextInt(10));
        ImageIO.write(service.genQrPay(new PayOrder("订单title", "摘要",
                price, System.currentTimeMillis() + "", AliTransactionType.SWEEPPAY)), "JPEG", baos);
        return baos.toByteArray();
    }

    /**
     * 获取二维码图像
     * 二维码支付
     *
     * @param price 金额
     * @return 二维码图像
     */
    @RequestMapping(value = "toQrPay.jpg2", produces = "image/jpeg;charset=UTF-8")
    public byte[] toWxQrPay2(BigDecimal price) throws IOException {
        //获取对应的支付账户操作工具（可根据账户id）
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        price = new BigDecimal(random.nextInt(10));
        PayOrder payOrder = new PayOrder("订单title", "摘要",
                price, System.currentTimeMillis() + "", AliTransactionType.SWEEPPAY);
        //----------支付订单入库
        AliOrderEntity aliOrder = new AliOrderEntity();
        aliOrder.setSubject(payOrder.getSubject());
        aliOrder.setBody(payOrder.getBody());
        aliOrder.setTotal_amount(payOrder.getPrice());
        aliOrder.setOut_trade_no(payOrder.getOutTradeNo());
        aliOrderService.add(aliOrder);
        //----------支付订单入库
        ImageIO.write(service.genQrPay(new PayOrder("订单title", "摘要",
                price, System.currentTimeMillis() + "", AliTransactionType.SWEEPPAY)), "JPEG", baos);
        return baos.toByteArray();
    }

    /**
     * 刷卡付,pos主动扫码付款(条码付)
     *
     * @param authCode 授权码，条码等
     * @param price    金额
     * @return 支付结果
     */
    @RequestMapping(value = "microPay")
    public Map<String, Object> microPay(BigDecimal price, String authCode) throws IOException {
        //获取对应的支付账户操作工具（可根据账户id）
        //条码付
        price = new BigDecimal(random.nextInt(10));
        PayOrder order = new PayOrder("huodull order", "huodull order", price, UUID.randomUUID().toString().replace("-", ""), AliTransactionType.BAR_CODE);
        //声波付
//        PayOrder order = new PayOrder("huodull order", "huodull order", null == price ? new BigDecimal(0.01) : price, UUID.randomUUID().toString().replace("-", ""), AliTransactionType.WAVE_CODE);
        //设置授权码，条码等
        order.setAuthCode(authCode);
        //支付结果
        Map<String, Object> params = service.microPay(order);
        //校验
        if (service.verify(params)) {

            //支付校验通过后的处理
            //......业务逻辑处理块........
        }
        //这里开发者自行处理
        return params;
    }

    /**
     * 支付回调地址
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "payBack.json")
    public String payBack(HttpServletRequest request) throws IOException {

        //获取支付方返回的对应参数
        Map<String, Object> params = service.getParameter2Map(request.getParameterMap(), request.getInputStream());
        if (null == params) {
            return service.getPayOutMessage("fail", "失败").toMessage();
        }
        System.out.println("-----------------------------------------------------------------");
        System.out.println("-------------接收到阿里的回调--------------------------------------");
        System.out.println("-------------回调参数如下:-----------------------------------------");
        System.out.println(JSON.toJSONString(params));
        System.out.println("-----------------------------------------------------------------");
        System.out.println("-------------回调校验结果:----------------------------------------");
        //--------------更新支付宝交易单---------------------------------
        String out_trade_no = String.valueOf(params.get("out_trade_no"));
        AliOrderEntity aliOrderEntity = new AliOrderEntity();
        aliOrderEntity.setOut_trade_no(out_trade_no);
        aliOrderEntity.setApp_id(String.valueOf(params.get("app_id")));
        aliOrderEntity.setSeller_id(String.valueOf(params.get("seller_id")));
        aliOrderEntity.setBuyer_id(String.valueOf(params.get("buyer_id")));
        aliOrderEntity.setBuyer_logon_id(String.valueOf(params.get("buyer_id")));
        aliOrderEntity.setNotify_id(String.valueOf(params.get("notify_id")));
        String notify_time = String.valueOf(params.get("notify_time"));
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            aliOrderEntity.setNotify_time(sdf.parse(notify_time));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        aliOrderEntity.setNotify_type(String.valueOf(params.get("notify_type")));
        aliOrderEntity.setTrade_no(String.valueOf(params.get("trade_no")));
        aliOrderEntity.setTrade_status(String.valueOf(params.get("trade_status")));
        aliOrderService.modifyByOutTradeNo(aliOrderEntity);
        //--------------更新支付宝交易单---------------------------------
        //校验
        if (service.verify(params)) {
            System.out.println("success");
            //这里处理业务逻辑
            //......业务逻辑处理块........
            return service.getPayOutMessage("success", "成功").toMessage();
        }
        System.out.println("fail");
        System.out.println("-----------------------------------------------------------------");
        return service.getPayOutMessage("fail", "失败").toMessage();
    }

    @RequestMapping(value = "payBack.html")
    public String payBackHtml(HttpServletRequest request) throws IOException {

        //获取支付方返回的对应参数
        Map<String, Object> params = service.getParameter2Map(request.getParameterMap(), request.getInputStream());
        if (null == params) {
            return service.getPayOutMessage("fail", "失败").toMessage();
        }
        System.out.println(JSON.toJSONString(params));
        String returnJson = JSON.toJSONString(params);
        //校验
        if (service.verify(params)) {
            System.out.println("success");
            //这里处理业务逻辑
            //......业务逻辑处理块........
            return service.getPayOutMessage("success", "成功").toMessage() + "\n" + returnJson;
        }
        System.out.println("fail");
        return service.getPayOutMessage("fail", "失败").toMessage() + "\n" + returnJson;
    }

    /**
     * 查询
     *
     * @param order 订单的请求体
     * @return 返回查询回来的结果集，支付方原值返回
     */
    @RequestMapping("query")
    public Map<String, Object> query(QueryOrder order) {
        return service.query(order.getTradeNo(), order.getOutTradeNo());
    }

    /**
     * 交易关闭接口
     *
     * @param order 订单的请求体
     * @return 返回支付方交易关闭后的结果
     */
    @RequestMapping("close")
    public Map<String, Object> close(QueryOrder order) {
        return service.close(order.getTradeNo(), order.getOutTradeNo());
    }

    /**
     * 申请退款接口
     *
     * @param order 订单的请求体
     * @return 返回支付方申请退款后的结果
     */
    @RequestMapping("refund")
    public Map<String, Object> refund(RefundOrder order) {
        return service.refund(order);
    }

    /**
     * 查询退款
     *
     * @param order 订单的请求体
     * @return 返回支付方查询退款后的结果
     */
    @RequestMapping("refundquery")
    public Map<String, Object> refundquery(QueryOrder order) {
        return service.refundquery(order.getTradeNo(), order.getOutTradeNo());
    }

    /**
     * 下载对账单
     *
     * @param order 订单的请求体
     * @return 返回支付方下载对账单的结果
     */
    @RequestMapping("downloadbill")
    public Object downloadbill(QueryOrder order) {
        return service.downloadbill(order.getBillDate(), order.getBillType());
    }

    /**
     * 通用查询接口，根据 AliTransactionType 类型进行实现,此接口不包括退款
     *
     * @param order 订单的请求体
     * @return 返回支付方对应接口的结果
     */
    @RequestMapping("secondaryInterface")
    public Map<String, Object> secondaryInterface(QueryOrder order) {
        TransactionType type = AliTransactionType.valueOf(order.getTransactionType());
        return service.secondaryInterface(order.getTradeNoOrBillDate(), order.getOutTradeNoBillType(), type);
    }

    /**
     * 转账
     *
     * @param order 转账订单
     * @return 对应的转账结果
     */
    @RequestMapping("transfer")
    public Map<String, Object> transfer(TransferOrder order) {
//        order.setOutNo("转账单号");
//        order.setPayeeAccount("收款方账户,支付宝登录号，支持邮箱和手机号格式");
//        order.setAmount(new BigDecimal(10));
//        order.setPayerName("付款方姓名, 非必填");
//        order.setPayeeName("收款方真实姓名, 非必填");
//        order.setRemark("转账备注, 非必填");
        //收款方账户类型 ,默认值 ALIPAY_LOGONID：支付宝登录号，支持邮箱和手机号格式。
        order.setTransferType(AliTransferType.ALIPAY_LOGONID);
        return service.transfer(order);
    }

    /**
     * 转账查询
     *
     * @param outNo   商户转账订单号
     * @param tradeNo 支付平台转账订单号
     * @return 对应的转账订单
     */
    @RequestMapping("transferQuery")
    public Map<String, Object> transferQuery(String outNo, String tradeNo) {
        return service.transferQuery(outNo, tradeNo);
    }

}
